package com.leon.alishop.spider.util;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.management.DescriptorKey;

import jodd.servlet.HtmlDecoder;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.apache.commons.lang.StringUtils;
import org.htmlparser.Node;
import org.htmlparser.Parser;
import org.htmlparser.beans.HTMLTextBean;
import org.htmlparser.beans.StringBean;
import org.htmlparser.tags.Bullet;
import org.htmlparser.tags.HeadingTag;
import org.htmlparser.tags.ImageTag;
import org.htmlparser.tags.ScriptTag;
import org.htmlparser.tags.Span;
import org.htmlparser.util.NodeList;
import org.htmlparser.util.ParserException;

import com.leon.alishop.core.enumeration.TaobaoStoreTypeEnum;
import com.leon.alishop.spider.model.TaobaoGoodsSKU;

/**
 * 商品详情页解析工具
 * 
 * @author Leon
 * 
 */
public class TaoBaoGoodsItemPageNodeParseUtil {

	public static int TAOBAO_SIZE_ID = 20509;
	public static int TAOBAO_COLOR_ID = 1627207;
	
	
	/**
	 * 解析缩略图
	 * 
	 * @param parser
	 * @return
	 * @throws ParserException
	 */
	public static String[] parseThumbnail(Parser parser) throws ParserException {
		NodeList nodeList = parser.extractAllNodesThatMatch(NodeFilterUtil
				.getThumbnailFilter());
		String[] ret = null;
		if (null != nodeList && nodeList.size() > 0) {
			ImageTag tag;
			List<String> urlList = new ArrayList<String>();
			String _url;
			for (int i = 0, len = nodeList.size(); i < len; i++) {
				tag = (ImageTag) nodeList.elementAt(i);
				if (tag != null
						&& StringUtils.isNotBlank(_url = tag.getImageURL()))
					urlList.add(_url);
			}
			if (urlList.size() > 0)
				ret = urlList.toArray(new String[urlList.size()]);
		}
		return ret;
	}

	/**
	 * 解析商品名称
	 * 
	 * @param parser
	 * @return
	 * @throws ParserException
	 */
	public static String parseName(Parser parser) throws ParserException {
		NodeList nodeList = parser.extractAllNodesThatMatch(NodeFilterUtil.getGoodsNameFilter());
		String ret = null;
		if (null != nodeList && nodeList.size() > 0) {
			HeadingTag tag = (HeadingTag) nodeList.elementAt(0);
			String text = null;
			if (tag != null && StringUtils.isNotBlank(text = tag.getChildrenHTML()))
				return text;
		}
		return ret;
	}

	/**
	 * 解析价格
	 * 
	 * @param parser
	 * @return
	 * @throws ParserException
	 */
	public static Integer parsePrice(Parser parser) throws ParserException {
		NodeList nodeList = parser.extractAllNodesThatMatch(NodeFilterUtil.getGoodsPriceFilter(TaobaoStoreTypeEnum.VERSION_2012));
		Integer ret = null;
		if (null != nodeList && nodeList.size() > 0) {
			Node tag = nodeList.elementAt(0);
			String text = null;
			if (tag != null &&
					(tag = tag.getNextSibling()) != null
					&& StringUtils.isNotBlank(text = tag.getText())) {
				try {
					if(text.indexOf("-")>0){
						text = text.substring(0,text.indexOf("-")).trim();
					}
					Float f = Float.valueOf(text.trim());
					ret = (int) (f * 100f);
				} catch (Exception e) {
				}
			}
		}
		if(ret != null)
			return ret;
		parser.reset();
		nodeList = parser.extractAllNodesThatMatch(NodeFilterUtil.getGoodsPriceFilter());
		if (null != nodeList && nodeList.size() > 0) {
			Node tag = nodeList.elementAt(0);
			String text = null;
			if (tag != null &&
					(tag = tag.getNextSibling()) != null
					&& StringUtils.isNotBlank(text = tag.getText())) {
				try {
					Float f = Float.valueOf(text.trim());
					ret = (int) (f * 100f);
				} catch (Exception e) {
				}
			}
		}
		return ret;
	}

	/**
	 * 解析销量
	 * 
	 * @param parser
	 * @return
	 * @throws ParserException
	 */
	@Deprecated
	public static Integer parseSaleVolume(Parser parser) throws ParserException {
		NodeList nodeList = parser.extractAllNodesThatMatch(NodeFilterUtil.getTotalSaleVolumeFilter());
		Integer ret = null;
		if (null != nodeList && nodeList.size() > 0) {
			Node tag = nodeList.elementAt(0);
			String text = null;
			if (tag != null 
					&& (tag = tag.getNextSibling()) != null
					&& StringUtils.isNotBlank(text = tag.getText())) {
				try {
					return Integer.valueOf(text);
				} catch (Exception e) {
				}
			}
		}
		return 0;
	}

	/**
	 * 解析浏览量
	 * 
	 * @param parser
	 * @return
	 * @throws ParserException
	 */
	@Deprecated
	public static Integer parseViewNum(Parser parser) throws ParserException {
		NodeList nodeList = parser.extractAllNodesThatMatch(NodeFilterUtil.getViewNumFilter());
		Integer ret = null;
		if (null != nodeList && nodeList.size() > 0) {
			Node tag = nodeList.elementAt(0);
			String text = null;
			if (tag != null 
					&& (tag = tag.getNextSibling()) != null
					&& StringUtils.isNotBlank(text = tag.getText())) {
				try {
					ret = Integer.valueOf(text);
				} catch (Exception e) {
					ret = 0;
				}
			}
		}
		return ret;
	}
	
	/**
	 * 解析收藏量
	 * 
	 * @param parser
	 * @return
	 * @throws ParserException
	 */
	@Deprecated
	public static Integer parseFavNum(Parser parser) throws ParserException {
		NodeList nodeList = parser.extractAllNodesThatMatch(NodeFilterUtil.getFavNumFilter());
		Integer ret = null;
		if (null != nodeList && nodeList.size() > 0) {
			Node tag = nodeList.elementAt(0);
			String text = null;
			if (tag != null 
					&& (tag = tag.getNextSibling()) != null){
				if(StringUtils.isNotBlank(text = tag.getText())){
					try {
						ret = Integer.valueOf(text);
					} catch (Exception e) {
						return 0;
					}
				}else{
					return 0;
				}
			}
		}
		return ret;
	}

	/**
	 * 解析属性
	 * 
	 * @param parser
	 * @return
	 * @throws ParserException
	 */
	public static Map<String, String> parseAttributes(Parser parser)
			throws ParserException {
		NodeList nodeList = parser.extractAllNodesThatMatch(NodeFilterUtil
				.getAttrFilter());
		Map<String, String> ret = new HashMap<String, String>();
		if (null != nodeList && nodeList.size() > 0) {
			Bullet tag;
			String text, attrName, attrVal;
			for (int index, i = 0, len = nodeList.size(); i < len; i++) {
				tag = (Bullet) nodeList.elementAt(i);
				if ((tag = (Bullet) nodeList.elementAt(i)) != null
						&& StringUtils.isNotBlank(text = tag.getStringText())
						&& text.indexOf(':') > 0) {
					index = text.indexOf(':');
					attrName = text.substring(0, index);
					attrVal = text.substring(index+1, text.length()).trim();
					if(attrVal != null){
						attrVal = HtmlDecoder.decode(attrVal);
					}
					if (StringUtils.isNotBlank(attrName)
							&& StringUtils.isNotBlank(attrVal)) {
						ret.put(attrName, attrVal);
					}
				}
			}
		}
		return ret;
	}

	/**
	 * 解析大图
	 * 
	 * @param parser
	 * @return
	 * @throws ParserException
	 */
	@Deprecated
	public static String[] parseBigImg(Parser parser) throws ParserException {
		NodeList nodeList = parser.extractAllNodesThatMatch(NodeFilterUtil
				.getBigImgFilter());
		String[] ret = null;
		if (null != nodeList && nodeList.size() > 0) {
			ImageTag tag;
			String text;
			List<String> srcList = new ArrayList<String>();
			for (int i = 0, len = nodeList.size(); i < len; i++) {
				if ((tag = (ImageTag) nodeList.elementAt(i)) != null
						&& StringUtils.isNotBlank(text = tag.getImageURL())) {
					srcList.add(text);
				}
			}
			if(srcList.size()>0){
				ret = srcList.toArray(new String[srcList.size()]);
			}
		}
		return ret;
	}
	
	public static String[] parseAjaxDescImg(Parser parser) throws ParserException{
		NodeList nodeList = parser.extractAllNodesThatMatch(NodeFilterUtil.getScriptFilter());
		if(null == nodeList || nodeList.size()==0)
			return null;
		ScriptTag tag;
		String text = null;
		boolean is = false;
		for (int i = 0, len = nodeList.size(); i < len; i++) {
			if ((tag = (ScriptTag) nodeList.elementAt(i)) != null
					&& StringUtils.isNotBlank(text = tag.getStringText())
					&& text.indexOf("Hub.config.set") > 0
					&& text.indexOf("\"valItemInfo\"") > 0
					&& text.indexOf("\"apiItemDesc\"") > 0) {
				is = true;
				break;
			}
		}
		if(!is){
			return null;
		}
		return sliptAjaxDescUrlScript(text);
	}
	/**
	 * 解析商品详情的ajax url
	 */
	private static String[] sliptAjaxDescUrlScript(String script){
		script = SpiderStringUtil.removeAllBlank(script);
		int indexof = script.indexOf("Hub.config.set('sku',{");
		if(indexof < 0){
			indexof = script.indexOf("Hub.config.set(\"sku\",{");
			if(indexof < 0)
				return null;
		}
		script = script.substring(indexof+"Hub.config.set('sku',{".length(), script.length());
		indexof = script.indexOf("\"apiItemDesc\":");
		if(indexof < 0){
			indexof = script.indexOf("'apiItemDesc':");
			if(indexof < 0)
				return null;
		}
		StringBuffer sb = new StringBuffer(300);
		char[] arr = script.substring(indexof+"'apiItemDesc':'".length(), script.length()).toCharArray();
		for (char c : arr) {
			if(c == '"' || c == '\'')
				break;
			sb.append(c);
		}
		String ajaxUrl;
		try {
			ajaxUrl = URLDecoder.decode(sb.toString(), "UTF-8");
		} catch (UnsupportedEncodingException e) {
			return null;
		}
		Parser parserDesc;
		try {
			parserDesc = new Parser(ajaxUrl);
		} catch (ParserException e1) {
			return null;
		}
		try {
			NodeList nodeList = parserDesc.extractAllNodesThatMatch(NodeFilterUtil
					.getBigImgFilter());
			String[] ret = null;
			if (null != nodeList && nodeList.size() > 0) {
				ImageTag tag;
				String text;
				List<String> srcList = new ArrayList<String>();
				for (int i = 0, len = nodeList.size(); i < len; i++) {
					if ((tag = (ImageTag) nodeList.elementAt(i)) != null
							&& StringUtils.isNotBlank(text = tag.getImageURL())) {
						srcList.add(text);
					}
				}
				if(srcList.size()>0){
					ret = srcList.toArray(new String[srcList.size()]);
				}
			}
			return ret;
		} catch (ParserException e) {
			return null;
		}
	}
	
	
	
	/**
	 * 解析SKU
	 * 
	 * @param parser
	 * @return
	 * @throws ParserException
	 */
	public static List<TaobaoGoodsSKU> parseSKU(Parser parser) throws ParserException {
		NodeList nodeList = parser.extractAllNodesThatMatch(NodeFilterUtil.getScriptFilter());
		List<TaobaoGoodsSKU> skuList = null;
		if (null != nodeList && nodeList.size() > 0) {
			ScriptTag tag;
			String text = null;
			boolean is = false;
			for (int i = 0, len = nodeList.size(); i < len; i++) {
				if ((tag = (ScriptTag) nodeList.elementAt(i)) != null
						&& StringUtils.isNotBlank(text = tag.getStringText())
						&& text.indexOf("Hub.config.set") > 0
						&& text.indexOf("\"valItemInfo\"") > 0
						&& text.indexOf("\"defSelected\"") > 0) {
					is = true;
					break;
				}
			}
			if(is){
				skuList = taobaoSkuList(splitSKUJsonScript(text));
			}
		}
		if(null == skuList
				|| skuList.size()==0){
			return Collections.emptyList();
		}
		parser.reset();
		Span node;
		int len = skuList.size();
		TaobaoGoodsSKU sku;
		String val;
		while (len-->0) {
			sku = skuList.get(len);
			parser.reset();
			nodeList = parser.extractAllNodesThatMatch(NodeFilterUtil.getSkuTagFilter(sku.getSizeId(), sku.getSizeValId()));
			if((node = (Span)nodeList.elementAt(0)) == null
					|| StringUtils.isBlank(val = node.getStringText())){
				skuList.remove(len);
				continue;
			}
			sku.setSizeValName(fomratSizeAndColorVal(val));
			parser.reset();
			nodeList = parser.extractAllNodesThatMatch(NodeFilterUtil.getSkuTagFilter(sku.getColorId(), sku.getColorValId()));
			if((node = (Span)nodeList.elementAt(0)) == null
					|| StringUtils.isBlank(val = node.getStringText())){
				skuList.remove(len);
				continue;
			}
			sku.setColorValName(fomratSizeAndColorVal(val));
		}
		if(null == skuList
				|| skuList.size()==0){
			return Collections.emptyList();
		}
		return skuList;
	}
	
	private static String splitSKUJsonScript(String script){
		script = SpiderStringUtil.removeAllBlank(script);
		int indexof = script.indexOf("Hub.config.set('sku',{");
		if(indexof < 0){
			indexof = script.indexOf("Hub.config.set(\"sku\",{");
			if(indexof < 0)
				return null;
		}
		script = script.substring(indexof+"Hub.config.set('sku',{".length(), script.length());
		indexof = script.indexOf("\"skuMap\":");
		if(indexof < 0){
			indexof = script.indexOf("'skuMap':");
			if(indexof < 0)
				return null;
		}
		StringBuilder sb = new StringBuilder();
		int acc = 0;
		char[] arr = script.substring(indexof+"'skuMap':".length(), script.length()).toCharArray();
		char c;
		for (int i = 0,len = arr.length; i < len; i++) {
			c = arr[i];
			if(c == '{')
				acc++;
			else if(c == '}')
				acc--;
			sb.append(c);
			if(acc == 0)
				break;
		}
		return sb.toString();
	}
	
	@SuppressWarnings("rawtypes")
	private static List<TaobaoGoodsSKU> taobaoSkuList(String json){
		if(StringUtils.isBlank(json))
			return Collections.emptyList();
		Map skuMap = null;
		try {
			skuMap = JSONObject.fromObject(json);
		} catch (Exception e) {
		}
		if(skuMap == null)
			return null;
		String key;
		Map cm;
		TaobaoGoodsSKU sku;
		List<TaobaoGoodsSKU> skuList = new ArrayList<TaobaoGoodsSKU>();
		String[] idArrs;
		int indexof;
		loop1:
		for (Object e : skuMap.keySet()) {
			key = e.toString();
			cm = (Map)skuMap.get(e);
			sku = new TaobaoGoodsSKU();
			if(cm.containsKey("skuId")
					&& cm.containsKey("price")
					&& cm.containsKey("stock")){
				try {
					sku.setSkuId(Long.valueOf(cm.get("skuId").toString()));
					sku.setPrice((int)(Float.valueOf(cm.get("price").toString())*100));
					sku.setStock(Integer.valueOf(cm.get("stock").toString()));
				} catch (Exception e2) {
					continue loop1;
				}
			}else{
				continue loop1;
			}
			idArrs = StringUtils.split(key, ";");
			if(null != idArrs && idArrs.length>0){
				for (String s : idArrs) {
					if(s != null && (indexof = s.indexOf(':')) > 0){
						if(StringUtils.isBlank(sku.getSizeName())){
							try {
								sku.setSizeId(Integer.valueOf(s.substring(0, indexof)));
								sku.setSizeName("尺码");
								sku.setSizeValId(Integer.valueOf(s.substring(indexof+1, s.length())));
							} catch (Exception e2) {
								continue loop1;
							}
						}else if(StringUtils.isBlank(sku.getColorName())){
							try {
								sku.setColorId(Integer.valueOf(s.substring(0, indexof)));
								sku.setColorName("颜色");
								sku.setColorValId(Integer.valueOf(s.substring(indexof+1, s.length())));
							} catch (Exception e2) {
								continue loop1;
							}
						}
					}
				}
			}
			if(StringUtils.isNotBlank(sku.getSizeName())
					&& StringUtils.isNotBlank(sku.getColorName()))
			skuList.add(sku);
		}
		return skuList;
	}
	private static String fomratSizeAndColorVal(String val){
		val = SpiderStringUtil.removeAllBlank(val);
		int indexof = val.indexOf("（");
		if(indexof > 0)
			return val.substring(0,indexof);
		indexof = val.indexOf("(");
		if(indexof > 0)
			return val.substring(0,indexof);
		return val;
	}

}
